# -*- coding: utf8 -*-

from google.appengine.ext import ndb
from google.appengine.api import memcache


class StatCnt(ndb.Model):
    """ base class for statistic
    cnt_guess: (ndb.IntegerProperty()) total amount of guessed word
    cnt_fail: (ndb.IntegerProperty()) total amount of failed word
    cnt_no_result: (ndb.IntegerProperty()) total amount of words which was\
        not guessed or failed in game
    """

    default_values = {
        'cnt_fail': 0,
        'cnt_guess': 0,
        'cnt_no_result': 0
    }

    def __init__(self, **kwargs):
        values = dict(self.default_values)
        values.update(kwargs)
        super(StatCnt, self).__init__(**values)


class TTimeToCnt(ndb.Model):
    """ Word statistic for one (total time)
    time_sec: (ndb.IntegerProperty()) total time the word was showed
    """

    cnt_guess = ndb.IntegerProperty(indexed=False)
    cnt_fail = ndb.IntegerProperty(indexed=False)
    cnt_no_result = ndb.IntegerProperty(indexed=False)

    time_sec = ndb.IntegerProperty(indexed=False)

    default_values = {
        'cnt_fail': 0,
        'cnt_guess': 0,
        'cnt_no_result': 0
    }

    def __init__(self, **kwargs):
        values = dict(self.default_values)
        values.update(kwargs)
        super(TTimeToCnt, self).__init__(**values)

    def key(self):
        return self.time_sec

    def merge(self, other_hist):
        self.cnt_fail += other_hist.cnt_fail
        self.cnt_guess += other_hist.cnt_guess
        self.cnt_no_result += other_hist.cnt_no_result


class LTimeAttemptNToCnt(ndb.Model):
    """ Word statistic for one (last attempt time and num of attempts)
    time_sec: (ndb.IntegerProperty()) time the word was showed in last attempt
    num_attempts: (ndb.IntegerProperty()) total number of attempts
    """

    cnt_guess = ndb.IntegerProperty(indexed=False)
    cnt_fail = ndb.IntegerProperty(indexed=False)
    cnt_no_result = ndb.IntegerProperty(indexed=False)

    time_sec = ndb.IntegerProperty(indexed=False)
    num_attempts = ndb.IntegerProperty(indexed=False)

    default_values = {
        'cnt_fail': 0,
        'cnt_guess': 0,
        'cnt_no_result': 0
    }

    def __init__(self, **kwargs):
        values = dict(self.default_values)
        values.update(kwargs)
        super(LTimeAttemptNToCnt, self).__init__(**values)

    def key(self):
        return (self.time_sec, self.num_attempts)

    def merge(self, other_hist):
        self.cnt_fail += other_hist.cnt_fail
        self.cnt_guess += other_hist.cnt_guess
        self.cnt_no_result += other_hist.cnt_no_result


class WordStatistic(ndb.Model):
    """ Word statistic
    hist_ltime_nattempt:(StructuredProperty(LTimeAttemptNToCnt, repeated=True))
    (last attempt time, num of attempts) -> (num of words every type)
    hist_ttime: (ndb.StructuredProperty(TTimeToCnt, repeated=True))
    (total time) -> (num of words every type)
    """
    hist_ltime_nattempt = ndb.LocalStructuredProperty(LTimeAttemptNToCnt,
                                                      repeated=True,
                                                      indexed=False)
    hist_ttime = ndb.LocalStructuredProperty(TTimeToCnt, repeated=True,
                                             indexed=False)
    word = ndb.StringProperty()

    cache_key = "word_statistic_by_text_"

    @staticmethod
    def get_by_word(word):
        word_key = memcache.get(WordStatistic.cache_key + repr(word))
        if word_key is not None:
            word_stat = word_key.get()
        else:
            word_stat = WordStatistic.query().filter(
                WordStatistic.word == word).get()
            if word_stat is None:
                return None
            memcache.set(WordStatistic.cache_key + repr(word),
                         word_stat.key)
        return word_stat

    def put(self):
        super(WordStatistic, self).put()
        memcache.set(WordStatistic.cache_key + repr(self.word),
                     self.key)


def histogram_update(histogram, new_element):
    """ add new element to histogram

    Args:
    histogram: (ndb.StructuredProperty(<StatClass>, repeated=True)
    new_element: (<StatClass>) element to put in histogram
    """

    for elem in histogram:
        if elem.key() == new_element.key():
            elem.merge(new_element)
            return
    # it is a new key
    histogram.append(new_element)
